#ifndef SERVER_H
#define SERVER_H

#include <map>
#include <string>
#include <memory>
#include <regex>
#include <mutex>
#include <boost/thread.hpp>
#include <boost/regex.hpp>
#include <boost/asio.hpp>

#include "Util.h"
#include "Session.h"
#include "SCGI.h"

using boost::asio::ip::tcp;

namespace scgi
{

class Server;

class Clock
{
	friend Server;

private:
	Time time;
	std::mutex mutex;

private:
	Clock();
	void tick(int tick_count_);

public:
	Time now();
};

class Listener : public std::enable_shared_from_this<Listener>
{
public:
	typedef std::shared_ptr<Listener> pointer;

private:
	Server & server;

public:
	Listener(Server & server_);

	void start();
	void accept();

public:
	static Listener::pointer create(Server & server_);
};

class Server
{
	friend Request;
	friend Listener;
	friend Application;
	friend SessionTable;

private:
	typedef std::map<std::string, Factory::pointer> factories_type;
	typedef std::pair<boost::regex, std::string> filter_type;
	typedef std::vector<filter_type> filters_type;

private:
	boost::asio::io_service service;
	tcp::acceptor acceptor;

	boost::thread_group threads;
	std::mutex mutex;
	boost::asio::io_service::work work;
	
	factories_type factories;
	filters_type filters;
	
	boost::asio::deadline_timer timer;

	Clock clock;
	SessionTable session_table;

	int buffer_size;

public:
	Server(unsigned short port_, std::string root_path_);

	void start(int thread_count_, int listener_count_);
	void join();
	void error(int code_);

	void setNameFilter(std::string regex_, std::string replace_);

private:
	void start_tick(int tick_count_);

public:
	void assign(Factory::pointer factory_);
	Application::pointer create(Request::pointer request_);
};

} // SCGI

#endif // SERVER_H
